const express = require('express');
const sqlite3 = require('sqlite3').verbose();
const cors = require('cors');
const app = express();
const port = 3000;

const PORT = process.env.PORT || 3000;



app.use(express.json());
app.use(cors());
app.use(express.static('public'));

// Initialize SQLite database
const db = new sqlite3.Database('./database.db', (err) => {
    if (err) {
        console.error("Database connection error:", err);
    } else {
        console.log("Connected to SQLite database.");
        initializeJobCardDatabase();
        initializePartsDatabase();
        initializeQuoteDatabase(); // Initialize quotes table
    }
});

// Function to create the `jobcards` table if it doesn't exist
function initializeJobCardDatabase() {
    db.run(`CREATE TABLE IF NOT EXISTS jobcards (
        jobCardNumber INTEGER PRIMARY KEY AUTOINCREMENT,
        clientName TEXT,
        contactNumber TEXT,
        email TEXT,
        dateReceived TEXT,
        productType TEXT,
        serialNumber TEXT,
        productNumber TEXT,
        warrantyStatus TEXT,
        reportedProblem TEXT,
        physicalCondition TEXT,
        clientConfirmationName TEXT,
        clientSignature TEXT,
        engineerName TEXT,
        engineerSignature TEXT,
        brandName TEXT,
        status TEXT DEFAULT 'New'
    )`);
}

function initializeTicketDatabase() {
    db.run(`CREATE TABLE IF NOT EXISTS tickets (
        ticketId INTEGER PRIMARY KEY AUTOINCREMENT,
        staffName TEXT,
        staffEmail TEXT,
        department TEXT,
        issueTitle TEXT,
        issueDescription TEXT,
        priority TEXT,
        status TEXT DEFAULT 'Open',
        dateCreated TEXT
    )`);
}


// Function to create the `parts` table to store part requests
function initializePartsDatabase() {
    db.run(`CREATE TABLE IF NOT EXISTS parts (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        jobCardNumber INTEGER,
        partName TEXT,
        quantity INTEGER,
        priority TEXT,
        FOREIGN KEY (jobCardNumber) REFERENCES jobcards(jobCardNumber)
    )`);
}

// Function to create the `quotes` and `quote_items` tables if they don't exist
function initializeQuoteDatabase() {
    db.run(`CREATE TABLE IF NOT EXISTS quotes (
        quoteNumber INTEGER PRIMARY KEY AUTOINCREMENT,
        clientName TEXT,
        contactPerson TEXT,
        clientEmail TEXT,
        clientPhone TEXT,
        dateIssued TEXT,
        validUntil TEXT,
        quoteDescription TEXT,
        dueDate TEXT,
        paymentMethods TEXT,
        additionalNotes TEXT,
        printedBy TEXT,
        subtotal REAL,
        vat REAL,
        totalAmount REAL,
        status TEXT DEFAULT 'pending'
    )`);

    db.run(`CREATE TABLE IF NOT EXISTS quote_items (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        quoteNumber INTEGER,
        description TEXT,
        quantity INTEGER,
        unitPrice REAL,
        totalPrice REAL,
        FOREIGN KEY (quoteNumber) REFERENCES quotes(quoteNumber)
    )`);
}

// Endpoint to add a new job card
app.post('/job-cards', (req, res) => {
    const {
        clientName, contactNumber, email, dateReceived, productType, serialNumber,
        productNumber, warrantyStatus, reportedProblem, physicalCondition,
        clientConfirmationName, clientSignature, engineerName, engineerSignature, brandName
    } = req.body;

    db.run(
        `INSERT INTO jobcards (
            clientName, contactNumber, email, dateReceived, productType,
            serialNumber, productNumber, warrantyStatus, reportedProblem,
            physicalCondition, clientConfirmationName, clientSignature,
            engineerName, engineerSignature, brandName
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
            clientName, contactNumber, email, dateReceived, productType, serialNumber,
            productNumber, warrantyStatus, reportedProblem, physicalCondition,
            clientConfirmationName, clientSignature, engineerName, engineerSignature, brandName
        ],
        function (err) {
            if (err) {
                console.error("Error saving job card:", err);
                res.status(500).json({ error: "Failed to save job card" });
            } else {
                res.json({ jobCardNumber: this.lastID });
            }
        }
    );
});



// Endpoint to retrieve a specific job card by job card number
app.get('/jobcards/:jobCardNumber', (req, res) => {
    const jobCardNumber = req.params.jobCardNumber;
    db.get(`SELECT * FROM jobcards WHERE jobCardNumber = ?`, [jobCardNumber], (err, row) => {
        if (err) {
            res.status(500).json({ error: "Failed to retrieve job card." });
        } else if (row) {
            res.json(row);
        } else {
            res.status(404).json({ error: "Job card not found." });
        }
    });
});

// Endpoint to retrieve all job cards, optionally filtered by status
app.get('/jobcards', (req, res) => {
    const { status } = req.query;
    let query = `SELECT * FROM jobcards`;
    const params = [];
    if (status && status !== 'all') {
        query += ` WHERE status = ?`;
        params.push(status);
    }
    db.all(query, params, (err, rows) => {
        if (err) {
            res.status(500).json({ error: "Failed to retrieve job cards." });
        } else {
            res.json(rows);
        }
    });
});

// Endpoint to assign an engineer to a job card and update status
app.post('/jobcards/:jobCardNumber/assign', (req, res) => {
    const jobCardNumber = req.params.jobCardNumber;
    const { engineerName } = req.body;
    db.run(
        `UPDATE jobcards SET engineerName = ?, status = 'In Progress' WHERE jobCardNumber = ?`,
        [engineerName, jobCardNumber],
        function (err) {
            if (err) {
                res.status(500).json({ error: "Failed to assign engineer." });
            } else {
                res.json({ message: "Engineer assigned and status updated to 'In Progress'." });
            }
        }
    );
});

// Endpoint to add a new part request to the `parts` table and update job card status to "Waiting for Parts"
app.post('/jobcards/:jobCardNumber/request-part', (req, res) => {
    const { jobCardNumber } = req.params;
    const { partName, quantity, priority } = req.body;

    db.run(
        `INSERT INTO parts (jobCardNumber, partName, quantity, priority) VALUES (?, ?, ?, ?)`,
        [jobCardNumber, partName, quantity, priority],
        function (err) {
            if (err) {
                console.error("Error saving part request:", err);
                res.status(500).json({ error: "Failed to save part request" });
            } else {
                // Update job card status to "Waiting for Parts"
                db.run(
                    `UPDATE jobcards SET status = 'Waiting for Parts' WHERE jobCardNumber = ?`,
                    [jobCardNumber],
                    function (updateErr) {
                        if (updateErr) {
                            console.error("Error updating job card status:", updateErr);
                            res.status(500).json({ error: "Failed to update job card status" });
                        } else {
                            res.json({ message: "Part request saved successfully and job card status updated." });
                        }
                    }
                );
            }
        }
    );
});

// Endpoint to retrieve part requests for a specific job card
app.get('/jobcards/:jobCardNumber/parts', (req, res) => {
    const jobCardNumber = req.params.jobCardNumber;

    db.all(`SELECT * FROM parts WHERE jobCardNumber = ?`, [jobCardNumber], (err, rows) => {
        if (err) {
            res.status(500).json({ error: "Failed to retrieve part requests." });
        } else {
            res.json(rows);
        }
    });
});

// Endpoint to add a new quote and its items
app.post('/quotes', (req, res) => {
    const {
        clientName, contactPerson, clientEmail, clientPhone, dateIssued, validUntil,
        quoteDescription, dueDate, paymentMethods, additionalNotes, printedBy, subtotal, vat, totalAmount, items
    } = req.body;

    db.run(
        `INSERT INTO quotes (
            clientName, contactPerson, clientEmail, clientPhone, dateIssued, validUntil, 
            quoteDescription, dueDate, paymentMethods, additionalNotes, printedBy, 
            subtotal, vat, totalAmount
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [clientName, contactPerson, clientEmail, clientPhone, dateIssued, validUntil,
         quoteDescription, dueDate, paymentMethods, additionalNotes, printedBy, 
         subtotal, vat, totalAmount],
        function (err) {
            if (err) {
                console.error("Error saving quote:", err);
                res.status(500).json({ error: "Failed to save quote" });
            } else {
                const quoteNumber = this.lastID;
                const placeholders = items.map(() => '(?, ?, ?, ?, ?)').join(',');
                const itemValues = items.flatMap(item => [
                    quoteNumber, item.description, item.quantity, item.unitPrice, item.totalPrice
                ]);

                db.run(
                    `INSERT INTO quote_items (quoteNumber, description, quantity, unitPrice, totalPrice) VALUES ${placeholders}`,
                    itemValues,
                    function (err) {
                        if (err) {
                            console.error("Error saving quote items:", err);
                            res.status(500).json({ error: "Failed to save quote items" });
                        } else {
                            res.json({ quoteNumber });
                        }
                    }
                );
            }
        }
    );
});

// Endpoint to retrieve a quote and its items by quote number
app.get('/quotes/:quoteNumber', (req, res) => {
    const quoteNumber = req.params.quoteNumber;

    db.get(`SELECT * FROM quotes WHERE quoteNumber = ?`, [quoteNumber], (err, quote) => {
        if (err) {
            res.status(500).json({ error: "Failed to retrieve quote" });
        } else if (quote) {
            db.all(`SELECT * FROM quote_items WHERE quoteNumber = ?`, [quoteNumber], (err, items) => {
                if (err) {
                    res.status(500).json({ error: "Failed to retrieve quote items" });
                } else {
                    quote.items = items;
                    res.json(quote);
                }
            });
        } else {
            res.status(404).json({ error: "Quote not found" });
        }
    });
});

// Endpoint to retrieve all quotes with optional status filter
app.get('/quotes', (req, res) => {
    const { status } = req.query;
    let query = `SELECT * FROM quotes`;
    const params = [];
    if (status && status !== 'all') {
        query += ` WHERE status = ?`;
        params.push(status);
    }
    db.all(query, params, (err, rows) => {
        if (err) {
            res.status(500).json({ error: "Failed to retrieve quotes." });
        } else {
            res.json(rows);
        }
    });
});

// Endpoint to accept a quote by updating its status
app.post('/quotes/:quoteNumber/accept', (req, res) => {
    const quoteNumber = req.params.quoteNumber;
    db.run(
        `UPDATE quotes SET status = 'accepted' WHERE quoteNumber = ?`,
        [quoteNumber],
        function (err) {
            if (err) {
                res.status(500).json({ error: "Failed to accept quote." });
            } else {
                res.json({ message: "Quote accepted successfully." });
            }
        }
    );
});

// Endpoint to reject a quote by updating its status
app.post('/quotes/:quoteNumber/reject', (req, res) => {
    const quoteNumber = req.params.quoteNumber;
    db.run(
        `UPDATE quotes SET status = 'rejected' WHERE quoteNumber = ?`,
        [quoteNumber],
        function (err) {
            if (err) {
                res.status(500).json({ error: "Failed to reject quote." });
            } else {
                res.json({ message: "Quote rejected successfully." });
            }
        }
    );
});



// Endpoint to add a new ticket
app.post('/tickets', (req, res) => {
    const { staffName, staffEmail, department, issueTitle, issueDescription, priority, status } = req.body;
    const dateCreated = new Date().toISOString();

    db.run(
        `INSERT INTO tickets (staffName, staffEmail, department, issueTitle, issueDescription, priority, status, dateCreated) 
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
        [staffName, staffEmail, department, issueTitle, issueDescription, priority, status, dateCreated],
        function (err) {
            if (err) {
                console.error("Error creating ticket:", err);
                res.status(500).json({ error: "Failed to create ticket" });
            } else {
                res.json({ message: "Ticket created successfully", ticketId: this.lastID });
            }
        }
    );
});

// Endpoint to get all tickets
app.get('/tickets', (req, res) => {
    const { status } = req.query;
    let query = `SELECT * FROM tickets`;
    const params = [];

    if (status && status !== 'all') {
        query += ` WHERE status = ?`;
        params.push(status);
    }

    db.all(query, params, (err, rows) => {
        if (err) {
            res.status(500).json({ error: "Failed to retrieve tickets." });
        } else {
            res.json(rows);
        }
    });
});

// Endpoint to update the status of a ticket
app.post('/tickets/:ticketId/update-status', (req, res) => {
    const { ticketId } = req.params;
    const { status } = req.body;

    db.run(
        `UPDATE tickets SET status = ? WHERE ticketId = ?`,
        [status, ticketId],
        function (err) {
            if (err) {
                console.error("Error updating ticket status:", err);
                res.status(500).json({ error: "Failed to update ticket status" });
            } else if (this.changes === 0) {
                res.status(404).json({ error: "Ticket not found" });
            } else {
                res.json({ message: `Ticket status updated to ${status}` });
            }
        }
    );
});

// Endpoint to get a specific ticket by ID
app.get('/tickets/:ticketId', (req, res) => {
    const { ticketId } = req.params;

    db.get(`SELECT * FROM tickets WHERE ticketId = ?`, [ticketId], (err, row) => {
        if (err) {
            res.status(500).json({ error: "Failed to retrieve ticket" });
        } else if (row) {
            res.json(row);
        } else {
            res.status(404).json({ error: "Ticket not found" });
        }
    });
});



// Start the server
app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
});

// Endpoint to fetch products marked as 'Ready for Collection'
app.get('/ready-for-collection', (req, res) => {
    db.all(`SELECT * FROM jobcards WHERE status = 'Ready for Collection'`, [], (err, rows) => {
        if (err) {
            res.status(500).json({ error: "Failed to retrieve products ready for collection." });
        } else {
            res.json(rows);
        }
    });
});

// Endpoint to update product status to 'Delivered'
app.post('/jobcards/:jobCardNumber/deliver', (req, res) => {
    const jobCardNumber = req.params.jobCardNumber;
    db.run(
        `UPDATE jobcards SET status = 'Delivered' WHERE jobCardNumber = ?`,
        [jobCardNumber],
        function (err) {
            if (err) {
                res.status(500).json({ error: "Failed to update product status to Delivered." });
            } else {
                res.json({ message: `Product ${jobCardNumber} marked as Delivered.` });
            }
        }
    );
});


// Endpoint to update the status of a specific job card
app.post('/jobcards/:jobCardNumber/update-status', (req, res) => {
    const jobCardNumber = req.params.jobCardNumber;
    const { status } = req.body;

    db.run(
        `UPDATE jobcards SET status = ? WHERE jobCardNumber = ?`,
        [status, jobCardNumber],
        function (err) {
            if (err) {
                console.error("Error updating job card status:", err);
                res.status(500).json({ error: "Failed to update job card status" });
            } else if (this.changes === 0) {
                res.status(404).json({ error: "Job card not found" });
            } else {
                res.json({ message: `Job status updated to ${status}.` });
            }
        }
    );
});



app.post('/invoices', (req, res) => {
    const { quoteNumber } = req.body;

    db.get(
        `SELECT * FROM quotes WHERE quoteNumber = ?`,
        [quoteNumber],
        (err, quote) => {
            if (err) {
                res.status(500).json({ error: "Failed to retrieve quote." });
            } else if (quote) {
                db.run(
                    `INSERT INTO invoices (
                        quoteNumber, clientName, contactPerson, clientEmail, clientPhone,
                        dateIssued, bankName, bankAccount, subtotal, vat, totalAmount
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
                    [
                        quote.quoteNumber, quote.clientName, quote.contactPerson,
                        quote.clientEmail, quote.clientPhone, new Date().toISOString().split('T')[0],
                        quote.bankName, quote.bankAccount, quote.subtotal, quote.vat, quote.totalAmount
                    ],
                    function (invoiceErr) {
                        if (invoiceErr) {
                            res.status(500).json({ error: "Failed to generate invoice." });
                        } else {
                            res.json({ invoiceNumber: this.lastID });
                        }
                    }
                );
            } else {
                res.status(404).json({ error: "Quote not found." });
            }
        }
    );
});

app.get('/invoices', (req, res) => {
    db.all(
        `SELECT * FROM invoices`,
        [],
        (err, rows) => {
            if (err) {
                res.status(500).json({ error: "Failed to retrieve invoices." });
            } else {
                res.json(rows);
            }
        }
    );
});

app.post('/job-cards/:jobCardNumber/status', (req, res) => {
    const { jobCardNumber } = req.params;
    const { status } = req.body;

    db.run(
        `UPDATE jobcards SET status = ? WHERE jobCardNumber = ?`,
        [status, jobCardNumber],
        function (err) {
            if (err) {
                res.status(500).json({ error: "Failed to update job card status." });
            } else if (this.changes === 0) {
                res.status(404).json({ error: "Job card not found." });
            } else {
                res.json({ message: "Job card status updated successfully." });
            }
        }
    );
});

// Endpoint to retrieve an invoice by its number
// Consolidated Endpoint to Fetch Invoice by ID (with Quote and Items)
app.get('/invoices/:invoiceNumber', (req, res) => {
    const { invoiceNumber } = req.params;

    db.get(`SELECT * FROM invoices WHERE invoiceNumber = ?`, [invoiceNumber], (err, invoice) => {
        if (err) {
            res.status(500).json({ error: "Failed to fetch invoice." });
            return;
        }

        if (!invoice) {
            res.status(404).json({ error: "Invoice not found." });
            return;
        }

        // Fetch associated quote details
        db.get(`SELECT bankName, bankAccount FROM quotes WHERE quoteNumber = ?`, [invoice.quoteNumber], (err, quote) => {
            if (err) {
                res.status(500).json({ error: "Failed to fetch quote details." });
                return;
            }

            // Add bank details to invoice
            invoice.bankName = quote?.bankName || "N/A";
            invoice.bankAccount = quote?.bankAccount || "N/A";

            res.json(invoice);
        });
    });
});

